From 0ed0e371937cadb524abb1aa5d85789565cec7d6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 23:16:43 +0100 Subject: [PATCH] Some refactoring of domain creation/destruction. Interface name changes: 1. do_createdomain -> domain_create 2. domain_destruct -> domain_destroy Arch-specific changes: 1. arch_do_createdomain -> arch_domain_create This function now takes a domain pointer, not a VCPU pointer! Initialisation of VCPU0 must happen in alloc_vcpu_struct(). 2. free_perdomain_pt -> arch_domain_destroy This function must undo the work of arch_domain_create TODO: arch_domain_create() refactoring is not completed for ia64. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/domain.c | 10 +++--- xen/arch/ia64/xen/xensetup.c | 8 ++--- xen/arch/x86/domain.c | 64 ++++++++++++++++------------------- xen/arch/x86/setup.c | 4 +-- xen/common/dom0_ops.c | 2 +- xen/common/domain.c | 49 +++++++++++++++------------ xen/common/schedule.c | 11 ++++-- xen/include/asm-ia64/domain.h | 2 -- xen/include/xen/domain.h | 6 ++-- xen/include/xen/sched.h | 17 +++++----- 10 files changed, 91 insertions(+), 82 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 99b1646614..f8e7a0ffaf 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -67,10 +67,11 @@ unsigned long map_domain_page0(struct domain *); extern unsigned long dom_fw_setup(struct domain *, char *, int); /* this belongs in include/asm, but there doesn't seem to be a suitable place */ -void free_perdomain_pt(struct domain *d) +void arch_domain_destroy(struct domain *d) { - printf("free_perdomain_pt: not implemented\n"); + printf("arch_domain_destroy: not implemented\n"); //free_page((unsigned long)d->mm.perdomain_pt); + free_xenheap_page(d->shared_info); } static void default_idle(void) @@ -192,9 +193,8 @@ static void init_switch_stack(struct vcpu *v) memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); } -int arch_do_createdomain(struct vcpu *v) +int arch_domain_create(struct domain *d) { - struct domain *d = v->domain; struct thread_info *ti = alloc_thread_info(v); /* Clear thread_info to clear some important fields, like preempt_count */ @@ -255,7 +255,7 @@ int arch_do_createdomain(struct vcpu *v) printk("Can't allocate pgd for domain %d\n",d->domain_id); return -ENOMEM; } - printf ("arch_do_create_domain: domain=%p\n", d); + printf ("arch_domain_create: domain=%p\n", d); return 0; } diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 1b9dc72b75..12a9fd4820 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -281,7 +281,7 @@ void start_kernel(void) printk("About to call scheduler_init()\n"); scheduler_init(); idle_vcpu[0] = (struct vcpu*) ia64_r13; - idle_domain = do_createdomain(IDLE_DOMAIN_ID, 0); + idle_domain = domain_create(IDLE_DOMAIN_ID, 0); BUG_ON(idle_domain == NULL); late_setup_arch(&cmdline); @@ -339,14 +339,14 @@ printk("About to call sort_main_extable()\n"); /* Create initial domain 0. */ -printk("About to call do_createdomain()\n"); - dom0 = do_createdomain(0, 0); +printk("About to call domain_create()\n"); + dom0 = domain_create(0, 0); #ifdef CLONE_DOMAIN0 { int i; for (i = 0; i < CLONE_DOMAIN0; i++) { - clones[i] = do_createdomain(i+1, 0); + clones[i] = domain_create(i+1, 0); if ( clones[i] == NULL ) panic("Error creating domain0 clone %d\n",i); } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index db764760b1..b38147211a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -218,41 +218,35 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.flags = TF_kernel_mode; if ( is_idle_domain(d) ) + { percpu_ctxt[vcpu_id].curr_vcpu = v; - - if ( (v->vcpu_id = vcpu_id) != 0 ) + v->arch.schedule_tail = continue_idle_domain; + } + else { - v->arch.schedule_tail = d->vcpu[0]->arch.schedule_tail; - v->arch.perdomain_ptes = - d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT); + v->arch.schedule_tail = continue_nonidle_domain; } + v->arch.perdomain_ptes = + d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT); + + v->arch.guest_vtable = __linear_l2_table; + v->arch.shadow_vtable = __shadow_linear_l2_table; +#if defined(__x86_64__) + v->arch.guest_vl3table = __linear_l3_table; + v->arch.guest_vl4table = __linear_l4_table; +#endif + return v; } void free_vcpu_struct(struct vcpu *v) { - BUG_ON(v->next_in_list != NULL); - if ( v->vcpu_id != 0 ) - v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL; xfree(v); } -void free_perdomain_pt(struct domain *d) -{ - free_xenheap_pages( - d->arch.mm_perdomain_pt, - get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t))); - -#ifdef __x86_64__ - free_xenheap_page(d->arch.mm_perdomain_l2); - free_xenheap_page(d->arch.mm_perdomain_l3); -#endif -} - -int arch_do_createdomain(struct vcpu *v) +int arch_domain_create(struct domain *d) { - struct domain *d = v->domain; l1_pgentry_t gdt_l1e; int vcpuid, pdpt_order, rc; #ifdef __x86_64__ @@ -263,9 +257,7 @@ int arch_do_createdomain(struct vcpu *v) d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order); if ( d->arch.mm_perdomain_pt == NULL ) goto fail_nomem; - memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE << pdpt_order); - v->arch.perdomain_ptes = d->arch.mm_perdomain_pt; /* * Map Xen segments into every VCPU's GDT, irrespective of whether every @@ -279,18 +271,12 @@ int arch_do_createdomain(struct vcpu *v) d->arch.mm_perdomain_pt[((vcpuid << GDT_LDT_VCPU_SHIFT) + FIRST_RESERVED_GDT_PAGE)] = gdt_l1e; - v->arch.guest_vtable = __linear_l2_table; - v->arch.shadow_vtable = __shadow_linear_l2_table; - #if defined(__i386__) mapcache_init(d); #else /* __x86_64__ */ - v->arch.guest_vl3table = __linear_l3_table; - v->arch.guest_vl4table = __linear_l4_table; - d->arch.mm_perdomain_l2 = alloc_xenheap_page(); d->arch.mm_perdomain_l3 = alloc_xenheap_page(); if ( (d->arch.mm_perdomain_l2 == NULL) || @@ -327,13 +313,9 @@ int arch_do_createdomain(struct vcpu *v) goto fail_nomem; memset(d->shared_info, 0, PAGE_SIZE); - v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id]; SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); } - v->arch.schedule_tail = is_idle_domain(d) ? - continue_idle_domain : continue_nonidle_domain; - return 0; fail_nomem: @@ -346,6 +328,20 @@ int arch_do_createdomain(struct vcpu *v) return -ENOMEM; } +void arch_domain_destroy(struct domain *d) +{ + free_xenheap_pages( + d->arch.mm_perdomain_pt, + get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t))); + +#ifdef __x86_64__ + free_xenheap_page(d->arch.mm_perdomain_l2); + free_xenheap_page(d->arch.mm_perdomain_l3); +#endif + + free_xenheap_page(d->shared_info); +} + /* This is called by arch_final_setup_guest and do_boot_vcpu */ int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 39bf4a523d..fc92f39bfa 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -385,7 +385,7 @@ void __init __start_xen(multiboot_info_t *mbi) scheduler_init(); - idle_domain = do_createdomain(IDLE_DOMAIN_ID, 0); + idle_domain = domain_create(IDLE_DOMAIN_ID, 0); BUG_ON(idle_domain == NULL); set_current(idle_domain->vcpu[0]); @@ -487,7 +487,7 @@ void __init __start_xen(multiboot_info_t *mbi) acm_init(&initrdidx, mbi, initial_images_start); /* Create initial domain 0. */ - dom0 = do_createdomain(0, 0); + dom0 = domain_create(0, 0); if ( dom0 == NULL ) panic("Error creating domain 0\n"); diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 5b92dc75d3..3a33965201 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -208,7 +208,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) pro = i; ret = -ENOMEM; - if ( (d = do_createdomain(dom, pro)) == NULL ) + if ( (d = domain_create(dom, pro)) == NULL ) break; memcpy(d->handle, op->u.createdomain.handle, diff --git a/xen/common/domain.c b/xen/common/domain.c index b0af3ebaf2..de4f6c3f79 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -29,7 +29,7 @@ struct domain *domain_list; struct domain *dom0; -struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) +struct domain *domain_create(domid_t dom_id, unsigned int cpu) { struct domain *d, **pd; struct vcpu *v; @@ -46,25 +46,27 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) INIT_LIST_HEAD(&d->page_list); INIT_LIST_HEAD(&d->xenpage_list); + rangeset_domain_initialise(d); + if ( !is_idle_domain(d) ) + { set_bit(_DOMF_ctrl_pause, &d->domain_flags); + if ( evtchn_init(d) != 0 ) + goto fail1; + if ( grant_table_create(d) != 0 ) + goto fail2; + } - if ( !is_idle_domain(d) && - ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) ) - goto fail1; - - if ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) - goto fail2; + if ( arch_domain_create(d) != 0 ) + goto fail3; - rangeset_domain_initialise(d); + if ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) + goto fail4; d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); d->irq_caps = rangeset_new(d, "Interrupts", 0); - - if ( (d->iomem_caps == NULL) || - (d->irq_caps == NULL) || - (arch_do_createdomain(v) != 0) ) - goto fail3; + if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) + goto fail5; if ( !is_idle_domain(d) ) { @@ -82,12 +84,18 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) return d; + fail5: + free_vcpu(v); + fail4: + arch_domain_destroy(d); fail3: - rangeset_domain_destroy(d); + if ( !is_idle_domain(d) ) + grant_table_destroy(d); fail2: - grant_table_destroy(d); + if ( !is_idle_domain(d) ) + evtchn_destroy(d); fail1: - evtchn_destroy(d); + rangeset_domain_destroy(d); free_domain(d); return NULL; } @@ -256,16 +264,16 @@ void domain_pause_for_debugger(void) /* Release resources belonging to task @p. */ -void domain_destruct(struct domain *d) +void domain_destroy(struct domain *d) { struct domain **pd; atomic_t old, new; BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags)); - /* May be already destructed, or get_domain() can race us. */ + /* May be already destroyed, or get_domain() can race us. */ _atomic_set(old, 0); - _atomic_set(new, DOMAIN_DESTRUCTED); + _atomic_set(new, DOMAIN_DESTROYED); old = atomic_compareandswap(old, new, &d->refcnt); if ( _atomic_read(old) != 0 ) return; @@ -287,8 +295,7 @@ void domain_destruct(struct domain *d) evtchn_destroy(d); grant_table_destroy(d); - free_perdomain_pt(d); - free_xenheap_page(d->shared_info); + arch_domain_destroy(d); free_domain(d); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index f6668d3593..f2815d7d9f 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -100,6 +100,7 @@ struct vcpu *alloc_vcpu( v->vcpu_id = vcpu_id; v->processor = cpu_id; atomic_set(&v->pausecnt, 0); + v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; v->cpu_affinity = is_idle_domain(d) ? cpumask_of_cpu(cpu_id) : CPU_MASK_ALL; @@ -117,14 +118,20 @@ struct vcpu *alloc_vcpu( if ( vcpu_id != 0 ) { - v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; d->vcpu[v->vcpu_id-1]->next_in_list = v; - set_bit(_VCPUF_down, &v->vcpu_flags); + if ( !is_idle_domain(d) ) + set_bit(_VCPUF_down, &v->vcpu_flags); } return v; } +void free_vcpu(struct vcpu *v) +{ + /* NB. Rest of destruction is done in free_domain(). */ + sched_rem_domain(v); +} + struct domain *alloc_domain(void) { struct domain *d; diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 863def1ff5..3aac190963 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -10,8 +10,6 @@ #include #include -extern int arch_do_createdomain(struct vcpu *); - extern void domain_relinquish_resources(struct domain *); struct arch_domain { diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 4ebf0ca286..4fee8e74cb 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -13,13 +13,13 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id); extern void free_vcpu_struct(struct vcpu *v); -extern int arch_do_createdomain(struct vcpu *v); +extern int arch_domain_create(struct domain *d); + +extern void arch_domain_destroy(struct domain *d); extern int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c); -extern void free_perdomain_pt(struct domain *d); - extern void domain_relinquish_resources(struct domain *d); extern void dump_pageframe_info(struct domain *d); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index df7611a70b..e6b63ac324 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -181,17 +181,18 @@ extern struct vcpu *idle_vcpu[NR_CPUS]; struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); +void free_vcpu(struct vcpu *v); struct domain *alloc_domain(void); void free_domain(struct domain *d); -#define DOMAIN_DESTRUCTED (1<<31) /* assumes atomic_t is >= 32 bits */ +#define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */ #define put_domain(_d) \ - if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destruct(_d) + if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d) /* * Use this when you don't have an existing reference to @d. It returns - * FALSE if @d is being destructed. + * FALSE if @d is being destroyed. */ static always_inline int get_domain(struct domain *d) { @@ -199,7 +200,7 @@ static always_inline int get_domain(struct domain *d) do { old = seen; - if ( unlikely(_atomic_read(old) & DOMAIN_DESTRUCTED) ) + if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) ) return 0; _atomic_set(new, _atomic_read(old) + 1); seen = atomic_compareandswap(old, new, &d->refcnt); @@ -210,15 +211,15 @@ static always_inline int get_domain(struct domain *d) /* * Use this when you already have, or are borrowing, a reference to @d. - * In this case we know that @d cannot be destructed under our feet. + * In this case we know that @d cannot be destroyed under our feet. */ static inline void get_knownalive_domain(struct domain *d) { atomic_inc(&d->refcnt); - ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED)); + ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED)); } -extern struct domain *do_createdomain( +extern struct domain *domain_create( domid_t dom_id, unsigned int cpu); extern int construct_dom0( struct domain *d, @@ -228,7 +229,7 @@ extern int construct_dom0( extern int set_info_guest(struct domain *d, dom0_setvcpucontext_t *); struct domain *find_domain_by_id(domid_t dom); -extern void domain_destruct(struct domain *d); +extern void domain_destroy(struct domain *d); extern void domain_kill(struct domain *d); extern void domain_shutdown(struct domain *d, u8 reason); extern void domain_pause_for_debugger(void); -- 2.30.2